package cz.proks.easyhelpdesk.gwt.activity;

import java.util.Date;
import java.util.Map;

import com.google.gwt.event.shared.EventBus;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;

import cz.proks.easyhelpdesk.api.model.Category;
import cz.proks.easyhelpdesk.api.model.Helpdesk;
import cz.proks.easyhelpdesk.api.model.HelpdeskRole;
import cz.proks.easyhelpdesk.api.model.Thread;
import cz.proks.easyhelpdesk.api.model.ThreadMember;
import cz.proks.easyhelpdesk.api.model.Ticket;
import cz.proks.easyhelpdesk.api.model.base.Id;
import cz.proks.easyhelpdesk.gwt.ClientFactory;
import cz.proks.easyhelpdesk.gwt.Globals;
import cz.proks.easyhelpdesk.gwt.activity.base.RestrictedHelpdeskActivity;
import cz.proks.easyhelpdesk.gwt.place.HelpdeskMainPlace;
import cz.proks.easyhelpdesk.gwt.place.NewTicketPlace;
import cz.proks.easyhelpdesk.gwt.restapi.RestIdCallback;
import cz.proks.easyhelpdesk.gwt.restapi.ThreadMemberRestApi;
import cz.proks.easyhelpdesk.gwt.restapi.ThreadRestApi;
import cz.proks.easyhelpdesk.gwt.restapi.TicketRestApi;
import cz.proks.easyhelpdesk.gwt.ui.NewTicketView;
import cz.proks.easyhelpdesk.gwt.ui.base.RestrictedHelpdeskView;
import cz.proks.easyhelpdesk.gwt.utils.RestUtils;

public class NewTicketActivity extends RestrictedHelpdeskActivity<NewTicketPlace> implements NewTicketView.Presenter {
    private NewTicketView view;

    public NewTicketActivity(NewTicketPlace place, ClientFactory clientFactory, PlaceHistoryMapper placeMapper) {
        super(place, clientFactory, placeMapper);
        view = getClientFactory().getTicketView();
        view.setPresenter(this);
    }

    @Override
    protected RestrictedHelpdeskView getView() {
        return view;
    }

    @Override
    protected void onPermission(AcceptsOneWidget panel, EventBus eventBus) {
        Map<Long, Category> categoryMap = Globals.getCategoryMapFor(Globals.getCurrentHelpdesk());
        
        view.onErase();
        view.setCategories(categoryMap.values());
        
        panel.setWidget(view);

    }

    @Override
    public void saveTicket(final Ticket ticket) {
        final TicketRestApi ticketRestApi = new TicketRestApi();
        final ThreadRestApi threadRestApi = new ThreadRestApi();
        final ThreadMemberRestApi threadMemberRestApi = new ThreadMemberRestApi();
        
        final Helpdesk helpdesk = Globals.getCurrentHelpdesk();
        final Date created = new Date();
        final Thread thread = new Thread();

        completeTicket(ticket, created);

        if (!isTicketOkBeforeSave(ticket))
            return;

        thread.setCreated(created);

        // save thread
        threadRestApi.create(thread, new RestIdCallback() {

            @Override
            public void onIdSuccess(Id id) {
                thread.setId(id.getId());
                ticket.setThreadId(id.getId());

                // save ticket
                ticketRestApi.create(ticket, new RestIdCallback() {

                    @Override
                    public void onIdSuccess(Id id) {
                        ticket.setId(id.getId());

                        thread.setEntryTicketId(id.getId());
                        thread.getTickets().add(ticket);

                        // add ticket to thread
                        threadRestApi.update(thread, new RestUtils.Callback() {

                            @Override
                            public void onSuccess(JSONValue val) {
                                final ThreadMember threadMember = getDefaultThreadMember(thread);

                                // save thread member
                                threadMemberRestApi.create(threadMember, new RestIdCallback() {

                                    @Override
                                    public void onIdSuccess(Id id) {
                                        threadMember.setId(id.getId());

                                        final HelpdeskRole role = getCurrentHeldpeskRole();

                                        Globals.setThreadFor(threadMember, thread);
                                        Globals.getThreadMemberMapFor(Globals.getCurrentHelpdeskMember()).put(id.getId(), threadMember);

                                        // share ticket to other users
                                        threadMemberRestApi.shareForHelpdeskAndThreadAndRole(helpdesk.getId(), thread.getId(), role, new RestUtils.Callback() {

                                            @Override
                                            public void onSuccess(JSONValue val) {
                                                // redirect
                                                getClientFactory().getPlaceController().goTo(new HelpdeskMainPlace(helpdesk.getId()));
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });
            }
        });
    }

    private boolean isTicketOkBeforeSave(Ticket ticket) {
        if (ticket.getSubject() == null || ticket.getSubject().isEmpty()) {
            Window.alert(getClientFactory().getHelpdeskMessages().errorTicketSubjectEmpty());
            return false;
        }

        else if (ticket.getCategoryId() == null) {
            Window.alert(getClientFactory().getHelpdeskMessages().errorTicketCategoryEmpty());
            return false;
        }

        return true;
    }

    @Override
    public void cancel() {
        Helpdesk helpdesk = Globals.getCurrentHelpdesk();
        getClientFactory().getPlaceController().goTo(new HelpdeskMainPlace(helpdesk.getId()));
    }

    private void completeTicket(Ticket ticket, Date created) {
        ticket.setOwnerId(Globals.getCurrentUser().getId());
        ticket.setCreated(created);
    }

    private ThreadMember getDefaultThreadMember(Thread thread) {
        ThreadMember threadMember = new ThreadMember();

        threadMember.setHelpdeskMemberId(Globals.getCurrentHelpdeskMember().getId());
        threadMember.setThreadId(thread.getId());
        threadMember.setRead(true);

        return threadMember;
    }

    private HelpdeskRole getCurrentHeldpeskRole() {
        return Globals.getCurrentHelpdeskMember().getHelpdeskRoles().get(0);
    }   
}
